package org.xmap.ui.base;
/**
 * <p>基础结构，封装了一个窗口区域。</p>
 * @author Zealot
 * @version 1.0
 */
public final class Rect {
    /**
     * 区域的左上角坐标点。
     */
    public Point leftUp;
    /**
     * 区域的宽度。
     */
    public int width;
    /**
     * 区域的高度。
     */
    public int height;
    /**
     * 默认构造函数，左上角坐标点为（0，0），宽高都为0。
     */
    public Rect() {
        this(0, 0, 0, 0);
    }
    /**
     * 指定区域为参数的构造函数。
     * @param r Rect 指定区域。
     */
    public Rect(Rect r) {
        this(r.leftUp.x, r.leftUp.y, r.width, r.height);
    }
    /**
     * 指定左上角坐标、区域宽度和高度为参数的构造函数。
     * @param leftUp Point 左上角坐标点。
     * @param width int 区域宽度。
     * @param height int 区域高度。
     */
    public Rect(Point leftUp, int width, int height) {
        this(leftUp.x, leftUp.y, width, height);
    }
    /**
     * 指定左上角横坐标、纵坐标、区域宽度和高度为参数的构造函数。
     * @param leftUpX int 左上角横坐标。
     * @param leftUpY int 左上角纵坐标。
     * @param width int 区域宽度。
     * @param height int 区域高度。
     */
    public Rect(int leftUpX, int leftUpY, int width, int height) {
        this.leftUp = new Point(0, 0);
        this.setRect(leftUpX, leftUpY, width, height);
    }
    /**
     * 指定区域为参数，重置当前区域。
     * @param r Rect 指定的区域。
     */
    public void setRect(Rect r) {
        this.setRect(r.leftUp.x, r.leftUp.y, r.width, r.height);
    }
    /**
     * 指定左上角横纵坐标、区域宽度和高度为参数，重置当前区域。
     * @param leftUpX int 左上角横坐标。
     * @param leftUpY int 左上角纵坐标。
     * @param width int 区域宽度。
     * @param height int 区域高度。
     */
    public void setRect(int leftUpX, int leftUpY, int width, int height) {
        this.leftUp.setXY(leftUpX, leftUpY);
        this.width = width;
        this.height = height;
    }
    /**
     * 区域在横坐标方向移动指定的像素。
     * @param x int 移动的像素值。
     */
    public void moveX(int x) {
        this.leftUp.moveX(x);
    }
    /**
     * 区域在纵坐标方向移动指定的像素。
     * @param y int 移动的像素值。
     */
    public void moveY(int y) {
        this.leftUp.moveY(y);
    }
    /**
     * 区域在横纵坐标方向移动指定的像素。
     * @param x int 横坐标方向移动的像素值。
     * @param y int 纵坐标方向移动的像素值。
     */
    public void moveXY(int x, int y) {
        this.leftUp.moveXY(x, y);
    }
    /**
     * 判断当前区域是否覆盖目标区域。
     * @param r Rect 目标区域。
     * @return boolean 是否覆盖。
     */
    public boolean contain(Rect r) {
        if (this.leftUp.x <= r.leftUp.x
            && this.leftUp.y <= r.leftUp.y
            && this.leftUp.x + this.width - 1 >= r.leftUp.x + r.width - 1
            && this.leftUp.y + this.height - 1 >= r.leftUp.y + r.height - 1) {
            return true;
        }
        return false;
    }
    /**
     * 判断目标坐标是否和当前区域发生碰撞。
     * @param x int 横坐标。
     * @param y int 纵坐标。
     * @return boolean 是否碰撞。
     */
    public boolean collideWith(int x, int y) {
        if (x >= this.leftUp.x
            && x <= this.leftUp.x + this.width - 1
            && y >= this.leftUp.y
            && y <= this.leftUp.y + this.height - 1) {
            return true;
        }
        return false;
    }
    /**
     * 判断目标点是否和当前区域发生碰撞。
     * @param p Point 目标点。
     * @return boolean 是否碰撞。
     */
    public boolean collideWith(Point p) {
        return this.collideWith(p.x, p.y);
    }
    /**
     * 判断当前的矩形是否和目标区域已经发生碰撞。
     * @param rect Rect 目标区域。
     * @return boolean 是否碰撞。
     */
    public boolean collideWith(Rect rect) {
        // 判断否包容对方
        if (this.contain(rect)) {
            return true;
        }
        // 判断是否被对方包容
        if (rect.contain(this)) {
            return true;
        }
        // 判断对方的四个角是否和当前区域相交
        if (this.collideWith(rect.leftUp.x, rect.leftUp.y)
            || this.collideWith(rect.leftUp.x + rect.width - 1, rect.leftUp.y)
            || this.collideWith(rect.leftUp.x, rect.leftUp.y + rect.height - 1)
            || this.collideWith(rect.leftUp.x + rect.width - 1, rect.leftUp.y + rect.height - 1)) {
            return true;
        }
        // 判断当前的四个角是否和对方相交
        if (rect.collideWith(this.leftUp.x, this.leftUp.y)
            || rect.collideWith(this.leftUp.x + this.width - 1, this.leftUp.y)
            || rect.collideWith(this.leftUp.x, this.leftUp.y + this.height - 1)
            || rect.collideWith(this.leftUp.x + this.width - 1, this.leftUp.y + this.height - 1)) {
            return true;
        }
        return false;
    }
    /**
     * 计算指定区域和当前区域的中心距离的平方。
     * @param rect 目标区域。
     * @return 距离的平方。
     */
    public int distanceSquare(Rect rect) {
        int centralX = this.leftUp.x + (this.width >> 1);
        int centralY = this.leftUp.y + (this.height >> 1);
        int rectCentralX = rect.leftUp.x + (rect.width >> 1);
        int rectCentralY = rect.leftUp.y + (rect.height >> 1);
        int d1 = centralX - rectCentralX;
        int d2 = centralY - rectCentralY;
        return d1 * d1 + d2 * d2;
    }
}
